package sse

import (
	"bufio"
	"bytes"
	"io"
	"strconv"
)

type Decoder struct {
	scanner *bufio.Scanner
}

func NewDecoder(r io.Reader) *Decoder {
	return &Decoder{scanner: bufio.NewScanner(r)}
}

var (
	headerId    = []byte("id")
	headerEvent = []byte("event")
	headerData  = []byte("data")
	headerRetry = []byte("retry")
)

func (d *Decoder) ReadEvent() (*Event, error) {
	e := Event{}
	var ing bool
	for d.scanner.Scan() {
		row := d.scanner.Bytes()
		if len(row) == 0 { // 读到空行
			if ing { // 已完成一个事件
				break
			}
			continue // 读到意外的空行, 忽略掉
		}
		if row[0] == ':' { // 仅仅是个注释
			continue
		}
		ing = true
		colonIndex := -1
		for i, c := range row {
			if c == ':' {
				colonIndex = i
				break
			}
		}
		var field, value []byte
		if colonIndex == -1 { // 一行文本中不包含冒号，则整行文本会被解析成为字段名，其字段值为空。
			field = row
		} else {
			field, value = row[:colonIndex], bytes.TrimLeft(row[colonIndex+1:], " ")
		}

		switch {
		case bytes.EqualFold(field, headerId):
			e.Id = bytes.Clone(value)
		case bytes.EqualFold(field, headerEvent):
			e.Event = bytes.Clone(value)
		case bytes.EqualFold(field, headerData):
			e.Data = append(e.Data, append(value, '\n')...)
		case bytes.EqualFold(field, headerRetry):
			// 如果指定了一个非整数值，该字段将被忽略。
			e.Retry, _ = strconv.ParseInt(string(value), 10, 64)
		}
	}
	if err := d.scanner.Err(); err != nil {
		return nil, err
	}
	if ing {
		if len(e.Data) > 0 {
			e.Data = e.Data[:len(e.Data)-1]
		}
		return &e, nil
	}
	return nil, io.EOF
}
